package com.tbocek.android.ode.solver;

import java.util.ArrayList;
import java.util.List;

import com.google.common.collect.Lists;

/**
 * Represents the state of a system of equations.
 * @author Tim
 *
 */
public class SystemState {
	
	/**
	 * Creates a new system with no dependent variables initially.
	 */
	public SystemState() {
		mVariables = Lists.newArrayList();
	}
	
	/**
	 * Creates a new system with the specified number of dependent variables.
	 * @param dimensions Number of dependent variables.
	 */
	public SystemState(int dimensions) {
		mVariables = Lists.newArrayListWithCapacity(dimensions);
	}
	
	/**
	 * List of dependent variables.
	 */
	protected List<Float> mVariables = Lists.newArrayList();
	
	/**
	 * The independent variable (time).
	 */
	private float mTime;
	
	/**
	 * @return Returns the time represented by this system state.
	 */
	public float getTime() {
		return mTime;
	}
	
	/**
	 * @return Returns the dependent variables in the system.
	 */
	public List<Float> getVariables() {
		return mVariables;
	}

	/**
	 * @return A new SystemState object in the same state as this object.
	 */
	public SystemState copy() {
		SystemState s = this.emptyClone();
		s.mTime = mTime;
		s.mVariables = Lists.newArrayList(mVariables);
		return s;
	}
	
	protected SystemState emptyClone() {
		return new SystemState();
	}

	/**
	 * Creates a new SystemState that is an approximation of the state of the
	 * system using this SystemState as the initial conditions and a first-order
	 * approximation going forward.
	 * @param derivatives
	 * @param deltaT
	 * @return
	 */
	public SystemState firstOrderStepForward(float[] derivatives, float deltaT) {
		SystemState s = this.emptyClone();
		s.mTime = this.mTime + deltaT;
		s.mVariables = Lists.newArrayListWithCapacity(mVariables.size());
		for (int i = 0; i < mVariables.size(); ++i) {
			s.mVariables.set(i, mVariables.get(i) + derivatives[i] * deltaT);
		}
		
		return s;
	}
}
